// websocketpp 库的使用 ----  websocketpp 搭建服务器
// 该库是基于 asio 框架实现的

#include <iostream>

// 系统默认查找头文件只会查找 /usr/include 目录下的文件
// 指定头文件路径 : 创建服务器用 websocketpp/server.hpp

#include <websocketpp/server.hpp>

// 指定 asio 路径
#include <websocketpp/config/asio_no_tls.hpp>

typedef websocketpp::server<websocketpp::config::asio> wserver_t;

void open_h(wserver_t *server, websocketpp::connection_hdl h1)
{
}

void close_h(wserver_t *server, websocketpp::connection_hdl h1)
{
}

// 处理客户端发来的消息
void messgae_h(wserver_t *server, websocketpp::connection_hdl h1, wserver_t::message_ptr mesg)
{
    std::cout << "client say# " + mesg->get_payload() << std::endl;
    // Debug -- 向客户端回显消息
    server->send(h1, mesg->get_payload(), websocketpp::frame::opcode::text);
}

// 处理 http 请求
void http_h(wserver_t *server, websocketpp::connection_hdl h1)
{
    // 获取 h1 中对应的连接
    wserver_t::connection_ptr con = server->get_con_from_hdl(h1);
    std::stringstream ss;
    ss << "<!doctype html><html><head>"
       << "<title>hello websocket</title><body>"
       << "<h1>hello websocketpp</h1>"
       << "</body></head></html>";
    con->set_body(ss.str());
    con->set_status(websocketpp::http::status_code::ok);   
}

int main()
{
    // 1. 实例化 server 对象 -- 基于 asio -- server 是一个模版
    wserver_t webserver;
    // 2. 设置日志等级
    webserver.set_access_channels(websocketpp::log::alevel::none);
    // 3. 初始化 asio 模型
    webserver.init_asio();
    // 4. 设置业务回调函数 (自己实现 , 4个)
    webserver.set_open_handler(std::bind(open_h, &webserver, std::placeholders::_1));                              // 握手成功回调
    webserver.set_close_handler(std::bind(close_h, &webserver, std::placeholders::_1));                            // 关闭连接成功回调
    webserver.set_http_handler(std::bind(http_h, &webserver, std::placeholders::_1));                              // http 回调
    webserver.set_message_handler(std::bind(messgae_h, &webserver, std::placeholders::_1, std::placeholders::_2)); // 消息处理回调
    // 5. 设置监听端口 -- listen
    webserver.listen(8089);
    // 6. 获取客户端新连接 -- accept
    webserver.start_accept();
    // 7. 启动服务器
    webserver.run();

    return 0;
}